<template>
	<tiny-drawer dragable :title="config.title" :visible="config.drawer" width="800px"
		@update:visible="config.drawer = $event" :z-index="500" placement="right" @close="handleClose()">
		<a-spin :spinning="spinning">
			<a-row class="mb-2">
				<a-col :span="24">
					<a-card>
						<a-space :size="40">
							<span>
								版本：
							</span>

							<a-select v-model:value="config.currentVersion" @change="change">
								<a-select-option v-for="item in config.versionList" :key="item.version"
									:label="item.label" :value="item.id" />
							</a-select>
							<span>
								logLevel:
							</span>
							<a-select v-model:value="config.logLevel" style="width: 100px;">
								<a-select-option v-for="item in config.logLevelList" :key="item.code" :label="item.name"
									:value="item.code" />
							</a-select>
							<span>
								<span>调试:</span>
								<a-switch v-model:checked="config.localFrontDebug"></a-switch>
								<div style="width:100px">
									<a-input v-model:value="config.debugUrl" placeholder="请输入地址"
										@change="debugUrlChange" v-show="config.localFrontDebug" />
								</div>
							</span>
							<a-button type="primary" @click="compnentTest">测试</a-button>
						</a-space>
					</a-card>
				</a-col>
			</a-row>
			<a-row>
				<a-col :span="24">
					<a-card>
						<div class="grid-content" style="height: 100%;width:100%;">
							<div class="container" id="container" ref="ct">
							</div>

							<div class="container" id="componentContainer">
								<component v-if="config.dynamicCode" :is="config.dynamicCode"
									:input="config.componentInputData" :output="config.componentOutputData"></component>
							</div>

						</div>
					</a-card>
				</a-col>
			</a-row>
		</a-spin>
	</tiny-drawer>
	<a-modal v-model:open="config.stepTestFlag" title="请输入参数">
		<div class="jsoneditor" ref="jsonEditor" style="width: 100%; height: 600px;"></div>
		<template #footer>
			<span class="dialog-footer">
				<el-button @click="config.stepTestFlag = false">取消</el-button>
				<el-button type="primary" @click="stepTest">
					提交
				</el-button>
			</span>
		</template>
	</a-modal>
</template>

<script setup>
import { toRaw, ref, defineProps } from "vue";
import { Button } from "view-ui-plus";
import JsonEditor from 'jsoneditor';
import 'jsoneditor/dist/jsoneditor.min.css';
import processVersionContentApi from '@/api/process/processVersionContentApi'
import processTestApi from '@/api/process/processTestApi'
import processApi from '@/api/process/processApi'
import processComponentApi from '@/api/process/processComponentApi'
import deConfig from '@/config'
import { parseDefineToJson } from '@/utils'
import { message } from 'ant-design-vue';


const props = defineProps([
	"propertiesBackFill",
	"getProcessVersionId",
	"getResource",
	"getNodeProperties"
])

const config = ref({
	isMaximum: false,
	drawer: false,
	versionList: [],
	currentVersion: null,
	logLevelList: [],
	logLevel: "",
	dynamicCode: null,
	name: "",
	componentInputData: null,
	componentOutputData: null,
	title: "",
	data: null,
	localFrontDebug: false,
	debugUrl: "",
	activeFrameId: "",
	activeFrameCode: null,
	je: null,
	activeFrameData: null,
	stepTestFlag: null,
	whileGetDataFlag: false
})
const spinning = ref(false);

const jsonEditor = ref()
onMounted(() => {
	listenerMessage();
})


const getCurrentInputDefine = async () => {
	const versionId = props.getProcessVersionId();
	const resource = props.getResource();
	//需要调用后端查询接口定义
	const read = await processVersionContentApi.getCurrentInputDefine({
		id: versionId,
		processId: null,
		processVersion: config.value.currentVersion,
		resource: resource,
		stepCode: config.value.activeFrameId
	});
	return read;
}
const initJsonEditor = () => {
	const options = {
		"modes": ["code", "tree", "form", "text", "preview"],
		"mode": "code"
	}
	config.value.je = new JsonEditor(jsonEditor.value, options);
	updateTestJson();
}
const updateTestJson = async () => {
	const obj = await getCurrentInputDefine();
	let define = parseDefineToJson(obj);
	if (!define) {
		define = {
			"": ""
		};
	}
	config.value.je.update(define);
}
const compnentTest = () => {
	//手动保存一把先，保存完了在调用后端测试
	valueProcessor(async () => {
		//弹窗输入参数
		config.value.stepTestFlag = true;
		if (!config.value.je) {
			nextTick(() => {
				initJsonEditor()
			})
		} else {
			await updateTestJson();
		}
	});

}
const stepTest = async () => {

	//获取一把tid
	const tid = await processTestApi.getTid({});

	//获取xml
	const versionId = props.getProcessVersionId();
	const resource = props.getResource();

	const value = config.value.je.get();
	const obj = await processTestApi.stepRun({
		id: versionId,
		processId: null,
		processVersion: config.value.currentVersion,
		resource: resource,
		param: value,
		stepCode: config.value.activeFrameId,
		tid: tid
	});
	message.info("执行成功，结果=>" + JSON.stringify(obj));
}
const handleClose = (done) => {
	valueProcessor(() => {
		config.value.activeFrameData = null;
		config.value.activeFrameId = null;
		config.value.name = null;
		config.value.componentInputData = null;
		config.value.componentOutputData = null;
		config.value.dynamicCode = null;
		config.value.currentVersion = null;
		if (done) {
			done();
		}
	});
	config.value.drawer = false;
}
const saveAndGetResource = () => {
	valueProcessor();
	return props.getResource();
}
const queryLogLevelList = async () => {
	const data = await processApi.queryLogLevelList({});
	config.value.logLevelList = data;
}

const debugUrlChange = () => {
	document.getElementById('fm-' + config.value.activeFrameId).remove();
	createIframe();
}
const max = () => {
	config.value.isMaximum = true
	let dom = document.getElementById("propertiesFLag")
	dom.style.zIndex = "9999";
	config.value.originSize = {
		width: dom.clientWidth,
		height: dom.clientHeight
	}
	dom.classList.add('editor-fullscreen');
	let maxIcon = document.getElementById("lvvss");
	maxIcon.style.right = "20px"
	maxIcon.style.top = "30px";
	// toRaw(this.monacoEditor).layout({
	//   height: document.body.clientHeight,
	//   width: document.body.clientWidth
	// })
}
const valueProcessor = (done) => {
	let iframe = document.getElementById('fm-' + config.value.activeFrameId);
	if (iframe) {
		iframe.contentWindow.postMessage(JSON.stringify({
			type: "getData"
		}), "*");
		config.value.whileGetDataFlag = true;
		whileGetData(() => {
			config.value.versionList.forEach(v => {
				if (v.version == config.value.currentVersion) {
					config.value.activeFrameData.pluginId = v.id;
				}
			});
			config.value.activeFrameData.version = config.value.currentVersion;
			config.value.activeFrameData.logLevel = config.value.logLevel;
			props.propertiesBackFill(config.value.activeFrameId, config.value.activeFrameData);
			if (done) {
				done();
			}
		});
	} else {
		config.value.activeFrameData = config.value.componentOutputData;
		config.value.versionList.forEach(v => {
			if (v.version == config.value.currentVersion) {
				config.value.activeFrameData.pluginId = v.id;
			}
		});
		config.value.activeFrameData.version = config.value.currentVersion;
		config.value.activeFrameData.logLevel = config.value.logLevel;
		props.propertiesBackFill(config.value.activeFrameId, config.value.activeFrameData);
		if (done) {
			done();
		}
	}
}
const whileGetData = (callback) => {
	if (config.value.whileGetDataFlag) {
		if (config.value.activeFrameData != null) {
			config.value.whileGetDataFlag = false;
			callback();
			return;
		} else {
			nextTick(() => {
				whileGetData(callback);
			})
		}
	}
}
const show = async (code, id, name, data) => {
	if (!data) {
		data = {};
	}
	if (!code) {
		return;
	}
	await queryVersionList(code);
	await queryLogLevelList();
	var version = data.version;
	if (null == version) {
		version = config.value.versionList[0].version;
	}
	if (data.logLevel) {
		config.value.logLevel = data.logLevel;
	}
	config.value.localFrontDebug = false;
	config.value.debugUrl = "";
	config.value.currentVersion = version;
	config.value.drawer = true;
	config.value.name = name;
	config.value.title = name + "(" + id + ")";
	config.value.activeFrameId = id;
	config.value.activeFrameCode = code;
	config.value.data = data;

	console.log(code);

	nextTick(() => {
		createIframe();
	})

}
const createIframe = async () => {

	//创建iframe
	//先把下面的所有iframe隐藏起来
	var element = document.querySelector("#container");
	var childNodes = element.childNodes;
	if (childNodes && childNodes.length > 0) {
		childNodes.forEach(v => {
			v.style.display = "none";
		})
	}

	let iframe = document.getElementById('fm-' + config.value.activeFrameId);
	if (iframe) {
		iframe.style.display = "block";
		const data = { ...config.value.data }
		data.versionId = props.getProcessVersionId();
		data.resource = props.getResource();
		data.processVersion = config.value.currentVersion;
		data.stepCode = config.value.activeFrameId;

		iframe.contentWindow.postMessage(JSON.stringify({
			type: "setData",
			data: data
		}), "*");

	} else {
		const s = document.querySelector("#container");
		//创建一把
		iframe = document.createElement('iframe');
		iframe.name = "fm-" + config.value.activeFrameId;
		iframe.id = "fm-" + config.value.activeFrameId;
		iframe.frameBorder = "0";
		iframe.allow = "fullscreen";
		iframe.width = "100%";
		if (!s.offsetHeight) {
			iframe.height = s.parentElement.offsetHeight;
		} else {
			iframe.height = s.offsetHeight;
		}

		const host = deConfig.API_URL;

		spinning.value = true;

		let v = await processComponentApi.getHtml(config.value.activeFrameCode, config.value.currentVersion);
		if (!v) {
			//动态组件
			spinning.value = false;
			await appendDynamicComponent();
			return;
		}
		let cs = v.substring(0, v.lastIndexOf("</"));
		let end = v.substring(v.lastIndexOf("</"));
		cs += `<link type='text/javascript' id="css-fm-${config.value.activeFrameId}" rel="stylesheet" href="${host}/process/component/css?code=${config.value.activeFrameCode}&version=${config.value.currentVersion}"/>`;
		// cs += `<script type='text/javascript' id="script-jquery-fm-${id}">${jq}<\/script>`;
		cs += `<script type='text/javascript' id="script-framework-fm-${config.value.activeFrameId}">
        window.onload = function(){

        if(!window.accessGet){
            console.log("没有找到window.accessGet函数");
        }
                if(!window.accessSet){
            console.log("没有找到window.accessSet函数");
        }
        }
window.editor={
          data:null,
          getData:function(){
              if(window.bindData){
                  this.data = window.bindData;
              }
              if(window.accessGet){
                 this.data =  window.accessGet();
             }
          return this.data;
          },
          setData:function(data){
              if(window.bindData!=null){
                 var keys = Object.keys(data);
                      keys.forEach(v => {
                          window.bindData[v] = data[v];
                      })
              }
                  if(window.accessSet){
                      window.accessSet(data);
                  }
              this.data = data;
          }
          }<\/script>`;
		cs += `<script type='text/javascript' id="script-fm-${config.value.activeFrameId}" src="${host}/process/component/js?code=${config.value.activeFrameCode}&version=${config.value.currentVersion}"><\/script>`

		cs += `<script type='text/javascript' id="script-message-fm-${config.value.activeFrameId}">window.addEventListener("message", function(event) {
             var d= event.data;
             if(d){
                  var parse = null;
                 if(typeof d =='string'){
                         parse = JSON.parse(d);
                 }else{
                     parse = d;
                 }
                 if(parse&&parse.type=="setData"){
                     window.editor.setData(parse.data);
                 }else if(parse&&parse.type=="getData"){
                     let param = {
                         type:"getData",
                         data:window.editor.getData()
                     }
                     window.parent.postMessage(JSON.stringify(param),"*");
                 }
             }
});<\/script>`

		cs += end;
		const blob = new Blob([cs], {
			type: "text/html"
		});
		let objectURL = window.URL.createObjectURL(blob);
		if (config.value.localFrontDebug && config.value.debugUrl) {
			iframe.src = config.value.debugUrl;
		} else {
			iframe.src = objectURL;
		}

		//     iframe.src = "data:text/html;charset=utf-8," + window.encodeURIComponent(cs);
		s.append(iframe);
		iframe.onload = () => {
			const data = { ...config.value.data }
			data.versionId = props.getProcessVersionId();
			data.resource = props.getResource();
			data.processVersion = config.value.currentVersion;
			data.stepCode = config.value.activeFrameId;

			iframe.contentWindow.postMessage(JSON.stringify({ type: "setData", data: data }), "*");
			spinning.value = false;
		}
	}
}
const change = (d) => {
	let version = "";
	config.value.versionList.forEach(v => {
		if (v.id == d) {
			version = v.version;
		}
	});
	var s = config.value.activeFrameId;
	var b = config.value.name;
	var c = config.value.activeFrameCode;
	config.value.activeFrameData = null;
	valueProcessor(() => {
		let data = props.getNodeProperties(s);
		//  iframe.remove();
		let iframe = document.getElementById('fm-' + config.value.activeFrameId);
		if (iframe) {
			iframe.remove();
		}
		data.version = version;
		config.value.activeFrameData = null;
		show(c, s, b, data)
	})

}
const appendDynamicComponent = async () => {
	const data = { ...config.value.data }
	data.versionId = props.getProcessVersionId();
	data.resource = props.getResource();
	data.processVersion = config.value.currentVersion;
	data.stepCode = config.value.activeFrameId;

	config.value.componentInputData = data;
	config.value.componentOutputData = {};
	// console.log(this.componentInputData)
	config.value.dynamicCode = config.value.activeFrameCode;

}
const queryVersionList = async (code) => {
	const data = await processComponentApi.queryVersionList(code)
	// console.log(data);
	// this.$set(this, "tableData", data);
	config.value.versionList = data;
}
const listenerMessage = () => {
	window.addEventListener('message', (e) => {
		// 监听 message 事件
		const d = e.data;
		if (d && typeof (d) == 'string') {
			let json = {};
			try {
				json = JSON.parse(d);
			} catch (e) {
				console.log("不是一个json")
			}
			if (json.type == "getData") {
				config.value.activeFrameData = json.data;
			}
		}
	});
}

defineExpose({
	show
})
</script>
<style scoped>
/*.container {*/
/*  width: 1000px;*/
/*  height: 500px;*/
/*}*/

.editor-fullscreen {
	position: fixed !important;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: 100%;
	height: 100% !important;
	z-index: 1000;
}
</style>
